<!--
@Description:数据字典下拉框选择
@Author:zqy
@Date:2022-08-19 11:12:05
@Last Modified by:zqy
@Last Modified time:2022-08-19 11:12:05
 -->
<template>
  <div class="custom-select">
    <el-select
      ref="customSelect"
      v-model="currentCode"
      :placeholder="placeholder"
      :disabled="disabled"
      :clearable="clearable"
      :filterable="filterable"
      :multiple="multiple"
      :collapse-tags="collapseTags"
      v-bind="$attrs"
      @change="customSelectChange"
      @visible-change="isShowSelectOptions"
      @clear="customClear"
    >
      <slot></slot>
      <el-option
        v-for="(list, index) in selectOptions"
        :key="index"
        :label="list.dictName"
        :value="list.dictCode"
      />
    </el-select>
  </div>
</template>

<script>
import { getDictByType } from './apis'
export default {
  name:'QupDictSelect',
  props: {
    placeholder: {
      type: String,
      default: '请输入'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    clearable: {
      type: Boolean,
      default: true
    },
    filterable: {
      type: Boolean,
      default: false
    },
    // 是否多选
    multiple: {
      type: Boolean,
      default: false
    },
    // 多选时是否将选中值按文字的形式展示
    collapseTags: {
      type: Boolean,
      default: false
    },
    // 回显或select value值
    code: {
      type: [String, Number, Array],
      default: ''
    },
    name: {
      type: [String, Number, Array],
      default: ''
    },
    // 绑定的Label名称
    bindName: {
      type: [String, Array],
      default: 'dictName'
    },
    // 绑定的Label值
    bindValue: {
      type: [String, Array],
      default: 'dictCode'
    },
    // 数据字典类型编码
    dictTypeCode: {
      type: String,
      default: '',
      required:true
    },
    // 业务域编码
    domainCode:{
      type:String,
      default:'',
      required:true
    },
    // 应用编码
    appCode:{
      type:String,
      default:'',
      required:true
    },
    // 是否开启取额外参数，当 emit为空时，取全部OBJ数据
    isEmit: {
      type: Boolean,
      default: false
    },
    // 所取值集合，该参数需开启 isEmit
    emitArr: {
      type: Array,
      default: () => ([])
    },
    includes: {
      // 包含指定的字典编码，若为Function则返回值需要是字典编码数组
      type: [Array,Function],
      default: undefined
    },
    excludes: {
      // 排除指定的字典编码，若为Function则返回值需要是字典编码数组
      type: [Array,Function],
      default: undefined
    }
  },
  data() {
    return {
      optList:[],
      currentCode: '',
      exCodeList:[],
      inCodeList:[]
    }
  },
  computed: {
    selectOptions() {
      let t = this.optList
      if (this.inCodeList instanceof Array && this.inCodeList.length>0) {
        t = t.filter(e => this.inCodeList.some(v=>v.toString()===e.dictCode.toString()))
      }
      if (this.exCodeList instanceof Array && this.exCodeList.length > 0) {
        t = t.filter(e =>!this.exCodeList.some(v=>v.toString()===e.dictCode.toString()))
      }
      return t
    }
  },
  watch: {
    code: {
      handler(newVal, oldVal) {
        if(this.multiple){
          this.currentCode = []
          if (newVal && newVal instanceof Array) {
            //延时处理el-select渲染报错
            setTimeout(() => {
              newVal.forEach(e => {
                if(!(e===null || e===undefined || e==='')){
                  this.currentCode.push(e.toString())
                }
              })
            }, 0)
          }
        }else{
          this.currentCode =(newVal===null || newVal===undefined) ? '': newVal.toString()
        }
      },
      immediate: true,
      deep: true
    },
    dictTypeCode: {
      handler(nv, ov) {
        this.getDictInfo()
      }
    },
  },
  created() {
    this.getCludeList()
    this.getDictInfo()
  },
  methods: {
    // 是否显示下拉框
    isShowSelectOptions(isShowSelectOptions) {
      if (!isShowSelectOptions) this.$refs.customSelect.blur()
    },
    // 获取数据字典信息
    getDictInfo() {
      /* if (Array.isArray(this.optList) && this.optList.length === 0) {
      } */
      let params = {}
      if (this.dictTypeCode && this.domainCode && this.appCode) {
        params = { dictTypeCode: this.dictTypeCode, appCode: this.appCode, domainCode: this.domainCode }
      } else {
        this.optList = []
        return
      }
      getDictByType(params).then(response => {
        if (Array.isArray(response.data) && response.data.length) {
          this.optList = response.data || []
          this.getCludeList()
        }
        this.$emit('data-change',this.optList)
      })
    },
    getCludeList(){
      let inCodeList = []
      if(this.includes){
        if(this.includes instanceof Array){
            inCodeList = this.includes
        }else if(this.includes instanceof Function){
          try {
            const result = this.includes()
            if (result instanceof Promise) {
              result.then((data) => {
                inCodeList = data instanceof Array ? data : []
              })
            } else {
              inCodeList = result instanceof Array ? result : []
            }
          } catch (e) {
            this.inCodeList = []
          }
        }
      }
      this.inCodeList = inCodeList

      let exCodeList = []
      if(this.excludes){
        if(this.excludes instanceof Array){
            exCodeList = this.excludes || []
        }else if(this.excludes instanceof Function){
          try {
            const result = this.excludes()
            if (result instanceof Promise) {
              result.then((data) => {
                exCodeList = data instanceof Array ? data : []
              })
            } else {
              exCodeList = result instanceof Array ? result : []
            }
          } catch (e) {
            exCodeList = []
          }
        }
      }
      this.exCodeList = exCodeList
    },
    
    customClear() {
      this.$emit('update:code', !!this.multiple ? [] :'')
      this.$emit('change',!!this.multiple ? [] :'')
    },
    // 下拉框值改变时
    customSelectChange(val) {
      // 判断选择中是否为空
      if (val === '' || (Array.isArray(val) && val.length === 0)) {
        this.currentCode = val
        if (Array.isArray(this.selectOptions) && this.selectOptions.length) {
          const k = this.selectOptions[0]
          if (typeof k === 'object' && Object.keys(k).length) {
            Object.keys(k).forEach(key => {
              this.$emit(`update:${key}`, '')
            })
          }
          this.$emit('update:code', !!this.multiple ? [] : '')
          this.$emit('update:name', '')
          this.$emit('change',!!this.multiple ? [] :'')
        }
        return
      }
      // 多选
      if (this.multiple) {
        if (Array.isArray(val) && val.length) {
          const selectArr = val.map(item => {
            const obj = this.selectOptions.find(list => {
              return list.dictCode === item
            })
            return obj
          })
          if (selectArr.length) {
            const keyArr = Object.keys(selectArr[0])
            const obj = {}
            selectArr.forEach(list => {
              keyArr.forEach(k => {
                obj[k] ? obj[k] += `,${list[k]}` : obj[k] = `${list[k]}`
              })
            })
            if (typeof obj === 'object' && Object.keys(obj).length) {
              if (this.isEmit) {
                if (Array.isArray(this.emitArr) && this.emitArr.length) {
                  this.emitArr.forEach(k => {
                    this.$emit(`update:${k}`, obj[k])
                  })
                } else {
                  Object.keys(obj).forEach(key => {
                    this.$emit(`update:${key}`, obj[key])
                  })
                }
              }
              this.$emit('update:code', obj.dictCode.split(','))
              this.$emit('update:name', obj.dictName || '')
              this.$emit('change', selectArr)
              return
            }
          }
        }
      }
      // 下拉框单选
      if (!this.multiple) {
        const obj = this.selectOptions.find(list => {
          return list.dictCode === val
        })
        if (typeof obj === 'object' && Object.keys(obj).length) {
          if (this.isEmit) {
            if (Array.isArray(this.emitArr) && this.emitArr.length) {
              this.emitArr.forEach(k => {
                this.$emit(`update:${k}`, obj[k])
              })
            } else {
              Object.keys(obj).forEach(key => {
                this.$emit(`update:${key}`, obj[key])
              })
            }
          }
          this.$emit('update:code', obj.dictCode)
          this.$emit('update:name', obj.dictName)
          this.$emit('change', obj)
          return
        }
      }
      this.$emit('update:code', val)
      this.$emit('update:name','')
      this.$emit('change', val)
    },
    /**
     * Object类型数组排序
     */
    arraySort(field) {
      return (a, b) => {
        const val1 = a[field]
        const val2 = b[field]
        return val1 - val2
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.custom-select {
  /deep/ .el-select {
    width: 100%;
  }
}
</style>
